import React from 'react';
import './pager.scss';

let BASE_SHIFT  = 0
  , TITLE_SHIFT = 1
  , TITLES = {
        first:   'First',
        prev:    '\u00AB',
        prevSet: '...',
        nextSet: '...',
        next:    '\u00BB',
        last:    'Last'
    };

let BLOCK_SIZE = 10;
let PAGE_RANGE = 5;
let PAGE_STEP  = 2;

class Pager extends React.Component {

    constructor(props) {
      super(props);
      this.state = {
        filters: this.props.filters || {},
        current: this.props.current || 0
      };

      this.__handlePreviousPage = this.__handlePreviousPage.bind(this);
      this.__handleNextPage     = this.__handleNextPage.bind(this);
      this.__handlePageChanged  = this.__handlePageChanged.bind(this);
      this.__calcBlocks         = this.__calcBlocks.bind(this);
      this.__isPrevDisabled     = this.__isPrevDisabled.bind(this);
      this.__isNextDisabled     = this.__isNextDisabled.bind(this);
      this.__isShouldHidden     = this.__isShouldHidden.bind(this);
      this.__visibleRange       = this.__visibleRange.bind(this);
      this.__pageJumpTo         = this.__pageJumpTo.bind(this);
      this.__jump               = this.__jump.bind(this);
      this.__renderPages        = this.__renderPages.bind(this);
    }


    /* ========================= HANDLERS =============================*/
    __handlePreviousPage() {
        if ( this.__isPrevDisabled() ) return;
        this.__handlePageChanged( this.state.current - TITLE_SHIFT );
    }

    __handleNextPage() {
        if ( this.__isNextDisabled() ) return;
        this.__handlePageChanged( this.state.current + TITLE_SHIFT );
    }

    __handlePageChanged( el ) {
        let handler = this.props.onPageChanged;
        this.setState({current: el});
        if ( handler ) handler(el);
    }


    /* ========================= HELPERS ==============================*/
    /**
     * Calculates "blocks" of buttons with page numbers.
     */
    __calcBlocks() {
        let props      = this.props
          , total      = props.total
          , current    = props.current + TITLE_SHIFT

          , blocks     = Math.ceil( total / BLOCK_SIZE )
          , currBlock  = Math.ceil( current / BLOCK_SIZE ) - TITLE_SHIFT;

        return {
            total:    blocks,
            current:  currBlock,
            size:     BLOCK_SIZE
        };
    }

    __isPrevDisabled() {
        return this.state.current <= BASE_SHIFT;
    }

    __isNextDisabled() {
        return this.state.current >= ( Math.ceil(this.props.total / BLOCK_SIZE) - TITLE_SHIFT );
    }

    __isShouldHidden() {
      return (Math.ceil(this.props.total / BLOCK_SIZE) <= 1);
    }

    __visibleRange() {
        let blocks  = this.__calcBlocks()
          , current = this.state.current
          , end     = blocks.total
          , delta   = end - current
          , start   = (current >= PAGE_STEP) ? current - PAGE_STEP : 0;

        let head   = (current <= PAGE_RANGE / 2)
          , middle = ((current >= PAGE_RANGE / 2) && (delta >= PAGE_RANGE / 2));

          //页数少于显示范围
          if(end <= PAGE_RANGE) {
            return [0 + TITLE_SHIFT, end + TITLE_SHIFT];
          }
          //页面接近第一页
          else if(head) {
            return [0 + TITLE_SHIFT, PAGE_RANGE + TITLE_SHIFT];
          }
          //页码位于中间位置
          else if(middle) {
            return [start + TITLE_SHIFT, (current + TITLE_SHIFT) + PAGE_STEP + TITLE_SHIFT];
          }
          //页码接近最后一页
          else {
            return [current - (PAGE_RANGE - delta) + TITLE_SHIFT, end + TITLE_SHIFT];
          }
    }

    /* ========================= RENDERS ==============================*/
    render() {
        let titles = this.getTitles;
        let css = this.__isShouldHidden() ? 'hidden' : '';

        return (
            <nav className={css}>
                <ul className="m-page">
                    <Page className="pageprv"
                          key="btn-first-page"
                          isDisabled={this.__isPrevDisabled()}
                          onClick={this.__handlePreviousPage}>上一页</Page>

                    {this.__renderPages( this.__visibleRange() )}

                    <Page className="pagenxt"
                          key="btn-next-page"
                          isDisabled={this.__isNextDisabled()}
                          onClick={this.__handleNextPage}>下一页</Page>
                    {/*<li className="m-jump"><span>共{Math.ceil(this.props.total / BLOCK_SIZE)}页
                   ，到第</span><input type="text" className="m-input-page" onChange={this.__pageJumpTo}/>页<button className="m-confirm-btn" onClick={this.__jump}>确定</button>
                    </li>*/}
                </ul>
            </nav>
        );
    }

    __pageJumpTo(event) {
      let page = event.target.value;

      this.setState({jumpTo: page});
    }

    __jump() {
      if(this.state.jumpTo) {
        let _current = this.state.jumpTo - 1;
        this.setState({current: _current});
        this.props.onPageChanged(_current);
      }
    }

    /**
     * ### __renderPages()
     * Renders block of pages' buttons with numbers.
     * @param {Number[]} range - pair of [start, from], `from` - not inclusive.
     * @return {React.Element[]} - array of React nodes.
     */
    __renderPages( pair ) {
        let self = this;

        function range ( start, end ) {
            let res = [];
            for ( let i = start; i < end; i++ ) {
                res.push( i );
            }

            return res;
        }

        return range( pair[0], pair[1] ).map(function ( el, idx ) {
            let current = el - TITLE_SHIFT
              , onClick = self.__handlePageChanged.bind(null, current)
              , isActive = (self.state.current === current);

            return (<Page key={idx} index={idx} isActive={isActive}
                          onClick={onClick}>{el}</Page>);
        });
    }
};



class Page extends React.Component {
    render () {
        let props = this.props;
        if ( props.isHidden ) return null;

        let baseCss = props.className ? props.className + ' ' : ''
          , css     = baseCss
                      + (props.isActive ? 'active' : '')
                      + (props.isDisabled ? ' disabled' : '');

        return (
            <li key={this.props.index} className={css}>
                <a onClick={this.props.onClick}>{this.props.children}</a>
            </li>
        );
    }
};

module.exports = Pager;
